package com.yunxin.yundubbo.connection;

import com.yunxin.yundubbo.codecs.MessageCodecs;
import com.yunxin.yundubbo.enums.HandlerEnum;
import com.yunxin.yundubbo.interfaces.DubboHandler;
import com.yunxin.yundubbo.mode.Message;
import com.yunxin.yundubbo.util.HandlerUtil;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
        import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class DubboService {

    private final NioEventLoopGroup boss;

    private final NioEventLoopGroup work;

    private Channel channel; // 添加channel引用用于管理

    public DubboService(int bossNumber, int workNumber) {
        this.boss = new NioEventLoopGroup(bossNumber);
        this.work = new NioEventLoopGroup(workNumber);
    }

    /**
     * 初始化并启动服务
     */
    public void start(String host, int port) {
        log.info("Starting Netty server on {}:{}", host, port);

        Runtime.getRuntime().addShutdownHook(new Thread(this::shutdown));

        try {
            ServerBootstrap bootstrap = new ServerBootstrap();
            bootstrap.group(boss, work)
                    .channel(NioServerSocketChannel.class)
                    .childHandler(new ChannelInitializer<NioSocketChannel>() {
                        @Override
                        protected void initChannel(NioSocketChannel ch) {
                            ChannelPipeline pipeline = ch.pipeline();
                            pipeline.addLast(new LengthFieldBasedFrameDecoder(102400,6 , 4, 0, 0))
                                    .addLast(new MessageCodecs())
                                    .addLast(new MessageHandler());
                        }
                    })
                    .option(ChannelOption.SO_BACKLOG, 128) // 添加TCP参数配置
                    .childOption(ChannelOption.SO_KEEPALIVE, true)
                    .childOption(ChannelOption.TCP_NODELAY, true);
            // 绑定端口并同步等待
            ChannelFuture future = bootstrap.bind(host, port).sync();
            this.channel = future.channel();

            future.addListener((ChannelFuture f) -> {
                if (f.isSuccess()) {
                    log.info("Netty server started successfully on {}:{}", host, port);
                } else {
                    log.error("Failed to start Netty server", f.cause());
                }
            });
        } catch (InterruptedException e) {
            log.error("Server interrupted", e);
            Thread.currentThread().interrupt();
        }
    }

    /**
     * 优雅关闭
     */
    public void shutdown() {
        log.info("Shutting down Netty server...");
        if (channel != null) {
            channel.close();
        }
        boss.shutdownGracefully();
        work.shutdownGracefully();
        log.info("Netty server shutdown complete");
    }

    /**
     * 消息处理器 - 改为非静态内部类以便访问外部类成员
     */
    private class MessageHandler extends ChannelInboundHandlerAdapter {

        @Override
        public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
            log.info("Received message: {}",ctx.channel());
            DubboHandler handler = HandlerUtil.getCacheHandler(HandlerEnum.REQUEST.getType());
            handler.handler(ctx,(Message)msg);
        }



        @Override
        public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
            log.error("Channel exception: {}", ctx.channel().remoteAddress(), cause);
            ctx.close();
        }

        @Override
        public void channelActive(ChannelHandlerContext ctx) throws Exception {
            log.info("Client connected: {}", ctx.channel().remoteAddress());
            super.channelActive(ctx);
        }

        @Override
        public void channelInactive(ChannelHandlerContext ctx) throws Exception {
            log.info("Client disconnected: {}", ctx.channel().remoteAddress());
            super.channelInactive(ctx);
        }
    }

    /**
     * 便捷的启动方法
     */
    public static DubboService createAndStart(int bossThreads, int workerThreads, String host, int port) {
        DubboService service = new DubboService(bossThreads, workerThreads);
        new Thread(() -> service.start(host, port)).start();
        return service;
    }
}